package cn.iocoder.yudao.module.erp.service.purchase;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.app.auth.vo.AppErpSupplierSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.app.erpSupplier.vo.AppErpSupplierUpdatePasswordReqVO;
import cn.iocoder.yudao.module.erp.controller.app.erpSupplier.vo.AppErpSupplierUpdateReqVO;
import cn.iocoder.yudao.module.erp.controller.app.erpSupplier.vo.ExceptionRemarkUpdateReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO;
import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpSupplierMapper;
import cn.iocoder.yudao.module.erp.enums.ErpSupplierStatus;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;

/**
 * ERP 供应商 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class ErpSupplierServiceImpl implements ErpSupplierService {

    @Resource
    private ErpSupplierMapper supplierMapper;
    @Resource
    private PasswordEncoder passwordEncoder;

    @Value("${task.supplier_apply.key:supplier_apply_audit}")
    private String supplierApplyTask;
    @Resource
    private BpmProcessInstanceApi processInstanceApi;

    @Value("${supplier.apply.user_id: 1}")
    private Long supplierApplyUserId;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createSupplier(ErpSupplierSaveReqVO createReqVO) {
        ErpSupplierDO supplier = BeanUtils.toBean(createReqVO, ErpSupplierDO.class);
        supplierMapper.insert(supplier);
         // 发起 BPM 流程
        return supplier.getId();
    }

    @Override
    public void updateSupplier(ErpSupplierSaveReqVO updateReqVO) {
        // 校验存在
        validateSupplierExists(updateReqVO.getId());
        // 更新
        ErpSupplierDO updateObj = BeanUtils.toBean(updateReqVO, ErpSupplierDO.class);
        supplierMapper.updateById(updateObj);
    }

    @Override
    public void deleteSupplier(Long id) {
        // 校验存在
        validateSupplierExists(id);
        // 删除
        supplierMapper.deleteById(id);
    }

    private ErpSupplierDO validateSupplierExists(Long id) {
        ErpSupplierDO erpSupplierDO = supplierMapper.selectById(id);
        if (erpSupplierDO == null) {
            throw exception(SUPPLIER_NOT_EXISTS);
        }else {
            return erpSupplierDO;
        }
    }

    @Override
    public ErpSupplierDO getSupplier(Long id) {
        return supplierMapper.selectById(id);
    }

    @Override
    public ErpSupplierDO validateSupplier(Long id) {
        ErpSupplierDO supplier = supplierMapper.selectById(id);
        if (supplier == null) {
            throw exception(SUPPLIER_NOT_EXISTS);
        }
        if (CommonStatusEnum.isDisable(supplier.getStatus())) {
            throw exception(SUPPLIER_NOT_ENABLE, supplier.getName());
        }
        return supplier;
    }

    @Override
    public List<ErpSupplierDO> getSupplierList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return supplierMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<ErpSupplierDO> getSupplierPage(ErpSupplierPageReqVO pageReqVO) {
        return supplierMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ErpSupplierDO> getSupplierListByStatus(Integer status) {
        return supplierMapper.selectListByStatus(status);
    }

    @Override
    public List<ErpSupplierDO> getSupplierList() {
        return supplierMapper.selectList();
    }

    @Override
    public int updateStatus(Long id, Integer status) {
        // 校验存在
        validateSupplierExists(id);
        // 更新
        ErpSupplierSaveReqVO updateReqVO = new ErpSupplierSaveReqVO();
        updateReqVO.setId(id);
        updateReqVO.setStatus(status);
        ErpSupplierDO updateObj = BeanUtils.toBean(updateReqVO, ErpSupplierDO.class);
        return supplierMapper.updateById(updateObj);

    }

    @Override
    public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createSupplier(AppErpSupplierSaveReqVO createReqVO) {
        //企业名称不能重复
        Long count = supplierMapper.selectCount(new LambdaQueryWrapper<ErpSupplierDO>()
                .eq(ErpSupplierDO::getName, createReqVO.getName())
        );
        if(count>0){
            throw new ServiceException("企业名称不能重复");
        }
        ErpSupplierDO supplier = BeanUtils.toBean(createReqVO, ErpSupplierDO.class);
        supplier.setStatus(ErpSupplierStatus.WAIT_AUDIT.getStatus());
        supplier.setPassword(passwordEncoder.encode(createReqVO.getPassword()));
        supplierMapper.insert(supplier);
        Map<String, Object> processInstanceVariables = new HashMap<>();
        processInstanceVariables.put("supplierId", supplier.getId());
        processInstanceVariables.put("supplierName", supplier.getName());
        processInstanceVariables.put("supplierLegalName",supplier.getLegalName());
        processInstanceVariables.put("supplierType", supplier.getType());
        processInstanceVariables.put("supplierContact", supplier.getCompanyContact());
        processInstanceVariables.put("supplierPhone", supplier.getCompanyTelephone());
        String processInstanceId = processInstanceApi.createProcessInstance(supplierApplyUserId,
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(supplierApplyTask)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(supplier.getId()))
        );
        ErpSupplierDO update = new ErpSupplierDO();
        update.setId(supplier.getId());
        update.setProcessInstanceId(processInstanceId);
        supplierMapper.updateById(update);
        return supplier.getId();
    }


    @Override
    public void updateSupplier(AppErpSupplierUpdateReqVO updateReqVO) {
        // 校验存在
        ErpSupplierDO erpSupplierDO = validateSupplierExists(updateReqVO.getId());
        if(erpSupplierDO.getStatus().equals(ErpSupplierStatus.AUDITING.getStatus())){
            throw exception(SUPPLIER_AUDITING, erpSupplierDO.getLegalName());
        }
        // 更新
        ErpSupplierDO updateObj = BeanUtils.toBean(updateReqVO, ErpSupplierDO.class);
        updateObj.setId(getLoginUserId());
        supplierMapper.updateById(updateObj);
    }

    @Override
    public void updateSupplierPassword(AppErpSupplierUpdatePasswordReqVO updatePasswordReqVO) {
        // 校验存在
        ErpSupplierDO erpSupplierDO = validateSupplierExists(getLoginUserId());
        if (!isPasswordMatch(updatePasswordReqVO.getOldPassword(), erpSupplierDO.getPassword())) {
            throw exception(SUPPLIER_PASSWORD_ERROR, erpSupplierDO.getName());
        }
        erpSupplierDO.setPassword(passwordEncoder.encode(updatePasswordReqVO.getNewPassword()));
        supplierMapper.updateById(erpSupplierDO);
    }

    @Override
    public void commit() {
        ErpSupplierDO erpSupplierDO = validateSupplierExists(getLoginUserId());
        if(!erpSupplierDO.getStatus().equals(ErpSupplierStatus.WAIT_AUDIT.getStatus())){
            throw exception(SUPPLIER_COMMIT_ERROR, erpSupplierDO.getName());
        }
        supplierMapper.updateById(new ErpSupplierDO().setId(getLoginUserId()).setStatus(ErpSupplierStatus.AUDITING.getStatus()));
    }

    @Override
    public void updateExceptionRemark(ExceptionRemarkUpdateReqVO updateReqVO) {
        ErpSupplierDO erpSupplierDO = validateSupplierExists(updateReqVO.getId());
        if(erpSupplierDO.getStatus().equals(ErpSupplierStatus.AUDITING.getStatus())){
            throw exception(SUPPLIER_AUDITING, erpSupplierDO.getLegalName());
        }
        ErpSupplierDO updateObj = new ErpSupplierDO();
        updateObj.setId(getLoginUserId());
        updateObj.setExceptionRemark(updateReqVO.getExceptionRemark());
        supplierMapper.updateById(updateObj);

    }


}
